#ifndef _INTERSECTION_H_
#define _INTERSECTION_H_

#include "vec3.h"
#include "vec2.h"

namespace math
{
///////////////////////////////////////////////////////
///	\brief	class for handling intersections
///////////////////////////////////////////////////////
class Intersection
{
public:
    /**
     * Test to see if the ray passes through an Axis Aligned Bounding Box
     * @param     _vMin        Low XYZ of box
     * @param     _vMax        High XYZ of box
     * @param     _From       Ray origin
     * @param     _To         Ray destination
     */
	static bool	RayAABB(const Vec3&	vMin,	const Vec3& _vMax, const Vec3& _vFrom, const Vec3& _vTo, Vec3& _vIntersection);

    /**
     * Test to see if the ray passes through a triangle
     * @param     orig       Ray origin
     * @param     dir         Ray direction
	 * @param vert0 The first vertex of the triangle.
	 * @param vert1 The second vertex of the triangle.
	 * @param vert2 The third vertex of the triangle.
	 * @param   t [out] Receives length along ray to the intersection if any.
     */
	static bool	RayTri(const Vec3& orig, const Vec3& dir, const Vec3& vert0, const Vec3& vert1, const Vec3& vert2, float* t );


    /**
     * Test to see if the ray passes through a sphere
     * @param     From      Ray origin
     * @param     To		Ray destination
     * @param     Center	Sphere center
     * @param     Radius	Sphere radius
	  * @param   Intersect[out] Where did the ray intersect the sphere 
     */
	static bool	RaySphere(const Vec3& From, const Vec3& To, const Vec3& Center, float Radius, math::Vec3& Intersect);


    /**
     * Test to see if the 2D ray passes through a circle
     * @param     From      Ray origin
     * @param     To		Ray destination
     * @param     Center	Sphere center
     * @param     Radius	Sphere radius
	  * @param   Intersect[out] Where did the ray intersect the sphere 
     */
	static bool	RayCircle(const Vec2& From, const Vec2& To, const Vec2& Center, float Radius, math::Vec2& Intersect);


    /**
     * Test to see if 2 2D aabbs overlap
	 * @param	MinA, MaxA	Min and Max of Box A
	 * @param	MinB, MaxB	Min and Max of Box B
	 * @returns	true if intersects
     */
	static bool	AABB2D(const math::Vec2& MinA, const math::Vec2& MaxA, const math::Vec2& MinB, const math::Vec2& MaxB);

	static bool SphereCapsule2D(const math::Vec2& Center, float Radius, const math::Vec2& From, const math::Vec2& To, float LineRad, float& Penetration, math::Vec2& Normal);
	static bool	AABBCapsule2D(const math::Vec2& Min, const math::Vec2& Max, const math::Vec2& From, const math::Vec2& To, float LineRad, float& Penetration, math::Vec2& Normal);
	static bool CapsuleCapsule2D(const math::Vec2& FromA, const math::Vec2& ToA, const math::Vec2& FromB, const math::Vec2& ToB, float LineRadA, float LineRadB);

	static math::Vec2		ClosestPointOnLine2D(const math::Vec2& A, const math::Vec2& B, const math::Vec2& P, bool segmentClamp = true);
	static float			DistanceToLine2D(const math::Vec2& A, const math::Vec2& B, const math::Vec2& P);
	static float			ClosestDistanceBetweenSegments2D(const math::Vec2& p1, const math::Vec2& p2, const math::Vec2& p3, const math::Vec2& p4, math::Vec2& PA, math::Vec2& PB);
	/**
	 * Test to see how close a point is to a line
	 * @param	Point			Point to test
	 * @param	Origin, Line	Ray (as defined by point + direction) to test
	 * @param	Nearest[out]	Closest point on the line
	 */
	static bool RayPoint(const Vec2& Point, const Vec2& Origin, const Vec2& Line, Vec2& Nearest);
	static bool	RayAABB2D(const Vec2&	vMin,	const Vec2& _vMax, const Vec2& _vFrom, const Vec2& _vTo, Vec2& _vIntersection);

	/**
	 * Test to see if a point is inside a simple polygon
	 * @param	v				Point to test
	 * @param	PointA			Array of Points defining the polygon
	 * @Param	PointC			Number of points
	 */
	static bool PointInsidePoly2D(const Vec2& v, Vec2* PointA, int PointC);
	static bool PointInsideRect2D(const Vec2& Point, const Vec2& Pos, const Vec2& Size, float Rot, bool IsCentered);
	static bool	PointInsideRect2DFast(const Vec2& Point, const Vec2& Pos, const Vec2& Size, bool IsCentered);
};

} // end namespace math


#endif // _INTERSECTION_H_